import { FilterPattern } from '@rollup/pluginutils'
import { CompilerOptions } from 'assemblyscript/cli/asc'

export interface EmscriptenModuleConfig {
  id: string,
  input: string | string[]
  includes?: string[]
  libDirs?: string[]
  libs?: string[]
  defines?: Record<string, string | undefined>
  jsTransfrom?: string[]
  jsLibrary?: string[]
  compilerArgv?: string[]
}

export interface UserOptions {
  inline?: boolean | number | ((fileName: string, id: string) => boolean | Promise<boolean>)
  useInstanceFactory?: boolean | CustomWebAssemblyInstanceFactory
  asc?: Omit<CompilerOptions, _OmitAscCompilerOptions> & {
    include?: FilterPattern
    exclude?: FilterPattern
    rename?: (id: string) => string
    dir?: string
    binaryDir?: string
    textDir?: string
    jsDir?: string
    idlDir?: string
    tsdDir?: string
  }
  emscripten?: Omit<EmscriptenModuleConfig, 'input' | 'id'> &  {
    modules?: EmscriptenModuleConfig[]
  }
  golang?: {
    include?: FilterPattern
    exclude?: FilterPattern
    goArgv?: string[]
    tinygo?: boolean
    tinygoArgv?: string[]
  }
  debug?: boolean
  target?: 'node'
}

export interface WebAssemblyModuleImportModuleId extends String {}
export interface Identifier extends String {}
export interface WebAssemblyModuleImportsTable {
  [name: WebAssemblyModuleImportModuleId & string]: Record<
    Identifier & string,
    WebAssembly.ImportExportKind
  >
}
export interface WebAssemblyModuleExportsTable {
  [name: Identifier & string]: WebAssembly.ImportExportKind
}
export interface GenerateCode extends String {}
export interface GenerateCode_ShouldExportDefault<T> extends GenerateCode {
  default?: T
}
export type GenerateCode_ShouldExportNamed<N extends Identifier, T> = GenerateCode & {
  [name in N & string]: T
}

export type CustomWebAssemblyInstanceFactory = (
  id: string,
  table: {
    imports: WebAssemblyModuleImportsTable
    exports: WebAssemblyModuleExportsTable
  }
) => GenerateCode_ShouldExportDefault<
  (
    createInstance: (
      importObject?: WebAssembly.Imports
    ) => WebAssembly.Instance | Promise<WebAssembly.Instance>,
    importObject?: WebAssembly.Imports,
    asynchronous?: boolean
  ) => any
>

type _OmitAscCompilerOptions =
  | 'version'
  | 'help'
  | 'outFile'
  | 'binaryFile'
  | 'textFile'
  | 'sourceMap'
  | 'noEmit'
  | 'debug'
  | 'noColors'
  | 'target'
  | 'listFiles'
